package com.bbbug.coree.controller;


import cn.hutool.core.collection.ConcurrentHashSet;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.bbbug.coree.entity.*;
import com.bbbug.coree.service.*;

import com.bbbug.coree.task.SongTask;
import com.bbbug.coree.utils.MiscUtil;
import com.bbbug.coree.utils.SpringUtils;
import com.bbbug.coree.websocketservice.core;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.BoundListOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.yeauty.pojo.Session;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
@RestController
@CrossOrigin(origins ="${myweb-path}" )
@EnableCaching
@RequestMapping("api/song")
public class SongController {
    RedisTemplate redisTemplate= SpringUtils.getBean("redistemp");
    @Autowired
    SongService songService;
    @Autowired
    SubscribeinfoService subscribeinfoService;
    @Autowired
    LrcinfoService lrcinfoService;
    @Autowired
    UserinfoService userinfoService;
    @Autowired
    RooominfoService roominfoService;
    @RequestMapping("addSong")
    ReturnData addSong(@RequestBody JSONObject mp){
        String access_token = mp.get("access_token").toString();
        String user1 = MiscUtil.verifyToken(access_token);
        String room_id = mp.get("room_id").toString();
        Roominfo roominfo=roominfoService.queryById(Integer.parseInt(room_id));
        if(roominfo.getRoom_type()==0){
            return new ReturnData(401,"文字聊天房不能点歌",null);
        }
        BoundListOperations roomops = redisTemplate.boundListOps(room_id);
        Long size = roomops.size();
        if(user1==null){
            return new ReturnData(401,"点歌失败 请先登陆",null);
        }else if(songisexit(room_id,mp.getLong("mid"))){
            return new ReturnData(403,"这首歌正在等待播放ing",null);
        }
        else if((roominfo.getRoom_addcount()!=null&&roominfo.getRoom_addcount()!=-1)&&roominfo.getRoom_addcount()<=size){
            return new ReturnData(403,"达到歌曲上限！ 请联系管理员加上限或者乖乖等待这一首放完",null);
        }else if(roominfo.getRoom_addsongcd()!=null&&roominfo.getRoom_addsongcd()!=-1){
            BoundHashOperations addsongcd = redisTemplate.boundHashOps("addsongcd");
            HashMap<String, Long> songcd = (HashMap<String, Long>) addsongcd.get(room_id);
            if(songcd==null){
                songcd=new HashMap<>();
                songcd.put(user1,System.currentTimeMillis());
            }else{
                if(songcd.get(user1)==null){
                    songcd.put(user1,System.currentTimeMillis());
                }else if(songcd.get(user1)+roominfo.getRoom_addsongcd()*1000<System.currentTimeMillis()){
                    songcd.put(user1,System.currentTimeMillis());
                }else{
                    return new ReturnData(403,"还有 "+((songcd.get(user1)+roominfo.getRoom_addsongcd()*1000-System.currentTimeMillis())/1000)+"秒才能点",null);
                }
            }
            addsongcd.put(room_id,songcd);
        }
            BoundHashOperations shutdown = redisTemplate.boundHashOps("songdown");
            HashMap<String, Long> jinyan = (HashMap<String, Long>) shutdown.get(room_id);
            if(jinyan!=null&&jinyan.get(user1)!=null){
                if(jinyan.get(user1)>=System.currentTimeMillis()){
                    return new ReturnData(403,"你被禁歌中！",null);
                }else{
                    jinyan.remove(user1);
                }
            }
        Object mid = mp.get("mid");
        songService.updateSong(Integer.parseInt(mid.toString()));
        Songinfo songinfo = querybyid(mid);
        JSONObject item = new JSONObject();
        if(size==0){
            long l = System.currentTimeMillis();
            item.put("at",false);
            item.put("since",l/1000);
            item.put("song", songinfo);
            item.put("end",(l+Long.valueOf(songinfo.getLength())*1000)/1000);
            item.put("type","playSong");
            item.put("story",null);
            item.put("count",size+1);
            item.put("user",userinfoService.queryById(Integer.parseInt(user1)));
            SendForALL(room_id,item.toJSONString());
        }else{
            JSONObject jsonObject = JSON.parseObject(roomops.index(size - 1).toString());
            Long since = Long.valueOf(jsonObject.get("end").toString());
            Long length = Long.valueOf(songinfo.getLength().toString());
            item.put("end",since+length);
            item.put("since",since);
            item.put("song", songinfo);
            item.put("type","addSong");
            item.put("story",null);
            item.put("count",size+1);
            item.put("user",userinfoService.queryById(Integer.parseInt(user1)));
            SendForALL(room_id,item.toJSONString());
        }
        roomops.rightPush(item.toJSONString());
        songinfo.setHot(0);
        item.put("song",songinfo);
        item.remove("user");
        item.remove("since");
        item.remove("end");
        item.remove("end");
        redisTemplate.opsForSet().add("history", item.toJSONString());
        List<Subscribeinfo> t1 = subscribeinfoService.queryForBoth(Integer.valueOf(mp.get("mid").toString()),Integer.parseInt(user1));
        if(t1.size()==0) {
            subscribeinfoService.insert(Integer.parseInt(mp.get("mid").toString()),Integer.parseInt(user1),1);
        } else {
            subscribeinfoService.update(Integer.valueOf(mp.get("mid").toString()), Integer.parseInt(user1));
        }
        return new ReturnData(200,"歌曲添加成功",mp.get("info"));
    }
    @RequestMapping("playSong")
    public ReturnData playSong(@RequestBody JSONObject mp){
        return addSong(mp);
    }
    public Songinfo querybyid(Object id){
        return songService.queryByMid(Integer.parseInt(id.toString()));
    }

    public Object querybykey(String key){
        List res = new Vector<>();
        JSONObject jsonObject=JSON.parseObject(MiscUtil.getres(key));
        JSONObject data = jsonObject.getJSONObject("data");
        if(data==null||data.equals(null)){
            return new JSONArray();
        } else{
            JSONArray list = data.getJSONArray("list");
            int len=list.size();
            for(int i=0;i<len;i++){
                JSONObject jtp = list.getJSONObject(i);
                JSONObject jitem = new JSONObject();
                jitem.put("pic", jtp.get("pic"));
                jitem.put( "mid", jtp.get("rid"));
                jitem.put( "mid", jtp.get("rid"));
                jitem.put("name", jtp.get("name"));
                jitem.put( "singer", jtp.get("artist"));
                jitem.put("length", jtp.get("duration"));
                res.add(jitem);
                /*jdbcTemplate.queryForList("select * from songinfo where mid=?",jtp.get("rid")).size()==0*/
                if(songService.queryByMid(Integer.parseInt(jtp.get("rid").toString()))==null){
                    Songinfo songinfo = new Songinfo();
                    songinfo.setMid(Long.parseLong(jtp.get("rid").toString()));
                    songinfo.setName(jtp.get("name").toString());
                    songinfo.setPic(jtp.get("pic").toString());
                    songinfo.setSinger(jtp.get("artist").toString());
                    songinfo.setLength(Integer.parseInt(jtp.get("duration").toString()));
                    songinfo.setHot(0);
                    songService.insert(songinfo);
                }
            }
            return res;

        }
    }
    @RequestMapping("/playurl")
    public void getplayurl(HttpServletResponse response,String mid) throws IOException {

        String body = HttpUtil.createGet("http://m.kuwo.cn/newh5app/api/mobile/v1/music/src/" + mid).execute().body();
        JSONObject jsonObject = JSON.parseObject(body);
        response.sendRedirect(jsonObject.getJSONObject("data").get("url").toString());
    }

    @RequestMapping("search")
    @Cacheable(value = "search_key",key = "#mp.get(\"keyword\")",condition = "#mp.get(\"keyword\")!=null" )
    public ReturnData search(@RequestBody JSONObject mp){
        if(mp.get("keyword")==null||mp.getInteger("isHots")==1){
            return new ReturnData(200,"ok",songService.queryByLimit());
        }else{
            return new ReturnData(200,"ok",querybykey(mp.getString("keyword")));
        }
    }
    @RequestMapping("/getLrc")//太大了不使用缓存 直接存储于数据库中
    public String getLrc(@RequestBody JSONObject mid){
        Lrcinfo lrcinfo = lrcinfoService.queryById(mid.getInteger("mid"));
        if(lrcinfo==null){
            String mid2 = MiscUtil.getLRC(mid.get("mid").toString());
            lrcinfoService.insert(Integer.parseInt(mid.get("mid").toString()),mid2);
            return mid2;
        }else{
            String lrc = lrcinfo.getLrc();
            return lrc;
        }
    }
    @RequestMapping("songList")
    ReturnData songList(@RequestBody Map mp){
        List<Object> r1 = redisTemplate.opsForList().range(mp.get("room_id").toString(), 1, -1);
        JSONArray jsonArray=new JSONArray();
        for(Object tp1:r1){
            jsonArray.add(JSONObject.parseObject(tp1.toString()));
        }
        return new ReturnData(200,"",jsonArray);
    }
    void SendForALL(String room_id,String message) {
        ConcurrentHashMap<String, Session> stringSessionConcurrentHashMap = core.CHATMAP.get(room_id);
        if (stringSessionConcurrentHashMap == null) {
            return ;
        }
        for (Session value : stringSessionConcurrentHashMap.values()) {
            value.sendText(message);
        }
    }
    @RequestMapping("addMySong")
    ReturnData addMySong(@RequestBody Map mp){
        String userid = MiscUtil.verifyToken(mp.get("access_token").toString());
        if(userid==null){
            return new ReturnData(403,"没权限QWQ",null);
        }else{
           List<Subscribeinfo> subscribeinfo = subscribeinfoService.queryForBoth(Integer.valueOf(mp.get("mid").toString()), Integer.parseInt(userid));
            if(subscribeinfo!=null) {
                subscribeinfoService.update(Integer.valueOf(mp.get("mid").toString()), Integer.parseInt(userid));
            }
             subscribeinfoService.insert(Integer.parseInt(mp.get("mid").toString()), Integer.parseInt(userid),1);
            return new ReturnData(200,"添加至歌单成功",null);
        }
    }
    @RequestMapping("mySongList")
    ReturnData mySongList(@RequestBody Map mp){
        String userid = MiscUtil.verifyToken(mp.get("access_token").toString());
        if(userid==null){
            return new ReturnData(200,"nothing",null);
        }
        else{
            List<SongSubinfo> maps = songService.queryByUserid(Integer.parseInt(userid));
            return new ReturnData(200,"获取成功",maps);
        }
    }
    @RequestMapping("getusersongs")
    ReturnData getusersongs(@RequestBody Map mp){
            List<SongSubinfo> maps = songService.queryByUserid(Integer.parseInt(mp.get("user_id").toString()));
            return new ReturnData(200,"获取成功",maps);
    }
    @RequestMapping("deleteMySong")
    ReturnData deleteMySong(@RequestBody Map mp){
        String userid = MiscUtil.verifyToken(mp.get("access_token").toString());
        if(userid==null){
            return new ReturnData(403,"没权限QWQ",null);
        }else{
            /*int update = jdbcTemplate.update("DELETE FROM  subscribeinfo WHERE mid=? and user_id=? ", mp.get("mid"), userid);*/
            Boolean update = subscribeinfoService.delete(Integer.parseInt(mp.get("mid").toString()),Integer.parseInt(userid));
            if(update){
                return new ReturnData(200,"成功",null);
            }
            return new ReturnData(403,"失败",null);
        }
    }
    @RequestMapping("remove")
    ReturnData removesong(@RequestBody JSONObject mp){
        String access_token = mp.get("access_token").toString();
        String s = MiscUtil.verifyToken(access_token);
        Object room_id=mp.get("room_id");
        if(s==null){
            return new ReturnData(403,"无权删除",null);
        }else{
            if(removebymid(room_id.toString(),mp.getLong("mid"))){
                JSONObject message = new JSONObject();
                message.put("type","removeSong");
                message.put("user",userinfoService.queryById(Integer.parseInt(s)));
                message.put("song",querybyid(mp.get("mid")));
                SendForALL(room_id.toString(),message.toJSONString());
                return new ReturnData(200,"删除成功",null);
            }else{
                return new ReturnData(403,"删除失败",null);
            }
        }
    }
    private static ConcurrentHashMap<String, ConcurrentHashSet<String>> nowpass = new ConcurrentHashMap<>();
    @RequestMapping("pass")
    ReturnData passsong(@RequestBody JSONObject mp){
        String access_token = MiscUtil.verifyToken(mp.get("access_token").toString());
        if(access_token==null) {
            return new ReturnData(401,"无权切歌!",null);
        }
        String room_id = mp.get("room_id").toString();
        Roominfo roominfo = roominfoService.queryById(mp.getInteger("room_id"));
        BoundListOperations roomops = redisTemplate.boundListOps(room_id);
        if(roomops.size()<=1){
            return new ReturnData(200,"没有下一首了qwq",null);
        }else if(roominfo.getRoom_votepass()!=null&&roominfo.getRoom_votepass()!=-1){
            if(nowpass.get(room_id)==null){
                nowpass.put(room_id,new ConcurrentHashSet<>());
            }
            boolean contains = nowpass.get(room_id).contains(access_token);
            if(contains){
                return new ReturnData(200,"你不想表态的态度成功",null);
            }
            nowpass.get(room_id).add(access_token);
            int size = core.CHATMAP.get(room_id).size();
            if(nowpass.get(room_id).size()<Math.ceil(size*1.0*roominfo.getRoom_votepass()/100)){//未达到要求
                JSONObject jsonObject = new JSONObject();
                jsonObject.put("content","有人表示不太喜欢当前播放的歌("+nowpass.size()+"/"+size+")");
                jsonObject.put("time",new Date());
                jsonObject.put("type","system");
                SendForALL(room_id,jsonObject.toJSONString());
                return new ReturnData(200,"你不想表态的态度成功",null);
            }else {
                nowpass.put(room_id,new ConcurrentHashSet<>());
            }
        }

            roomops.leftPop();
            SongTask.channelhome.put(room_id,System.currentTimeMillis());
            JSONObject jnow=JSON.parseObject(roomops.index(0).toString());
            jnow.put("since",System.currentTimeMillis()/1000);
            jnow.put("type","playSong");
            SendForALL(room_id,jnow.toJSONString());
            return new ReturnData(200,"成功",null);


    }
        @RequestMapping("push")
          public ReturnData pushsong(@RequestBody JSONObject mp){
            String access_token = MiscUtil.verifyToken(mp.get("access_token").toString());
            Integer room_id = mp.getInteger("room_id");
            Roominfo roominfo = roominfoService.queryById(room_id);
            if(access_token==null) {
                return new ReturnData(403,"无权顶歌!",null);
            }
            if(roominfo.getRoom_pushdaycount()!=null&&roominfo.getRoom_pushdaycount()!=-1){
                BoundHashOperations pushdaycount = redisTemplate.boundHashOps("pushdaycount");
                HashMap<Integer, Long> res = (HashMap<Integer, Long>) pushdaycount.get(room_id);
                Long aLong=0L;
                if(res==null) {
                    res=new HashMap<>();
                }
                else {
                    aLong= res.get(Integer.parseInt(access_token));
                    if(aLong+1>roominfo.getRoom_pushdaycount()){
                        return new ReturnData(403,"今天不能再顶了",null);
                    }
                }
                res.put(Integer.parseInt(access_token),aLong+1);
                pushdaycount.put(room_id,res);
            }
             if(roominfo.getRoom_pushsongcd()!=null&&roominfo.getRoom_pushsongcd()!=-1){
                BoundHashOperations pushsongcd = redisTemplate.boundHashOps("pushsongcd");
                HashMap<Integer, Long> res = (HashMap<Integer, Long>) pushsongcd.get(room_id);
                if(res==null){
                    res=new HashMap<>();
                }
                else if(res.get(room_id)!=null){
                    Long cd = res.get(room_id);
                    if(roominfo.getRoom_pushsongcd()*1000+cd>=System.currentTimeMillis()){
                        return new ReturnData(403,"终极技能 顶歌 还有 "+(roominfo.getRoom_pushsongcd()*1000+cd-System.currentTimeMillis())/1000+"秒",null);
                    }
                }
                res.put(room_id,System.currentTimeMillis());
                pushsongcd.put(room_id,res);
            }
                BoundListOperations boundListOperations = redisTemplate.boundListOps(room_id.toString());
                int pos=getsongpos(room_id.toString(),mp.getLong("mid"));
                if(pos==-1) {
                    return  new ReturnData(200,"顶歌失败 原因是没有找到这首歌",null);
                }
                JSONObject index1 = JSON.parseObject(boundListOperations.index(1).toString());
                JSONObject index2= JSON.parseObject(boundListOperations.index(pos).toString());
                boundListOperations.set(pos,index1.toJSONString());
                boundListOperations.set(1,index2.toJSONString());
                JSONObject message = new JSONObject();
                message.put("type","push");
                message.put("user_name",mp.get("user_name"));
                message.put("song",querybyid(mp.get("mid")));
                SendForALL(room_id.toString(),message.toJSONString());
                return new ReturnData(200,"顶好了",null);
         }
         //从1开始的原因是 0正在播放 不能对其修改
         boolean removebymid(String room_id,Long mid){
             BoundListOperations boundListOperations = redisTemplate.boundListOps(room_id);
             List range = boundListOperations.range(0, -1);
             for(int i=1;i<range.size();i++){
                 Object t1= range.get(i);
                 JSONObject jsonObject = JSONObject.parseObject(t1.toString());
                 Long aLong = jsonObject.getJSONObject("song").getLong("mid");
                 if(aLong.equals(mid)){
                     boundListOperations.remove(1,t1);
                     return true;
                 }
             }
             return false;
         }
         boolean songisexit(String room_id,Long mid){
             BoundListOperations boundListOperations = redisTemplate.boundListOps(room_id);
             List range = boundListOperations.range(0, -1);
             for(int i=1;i<range.size();i++){
                 String t1= (String)range.get(i);
                 JSONObject jsonObject = JSONObject.parseObject(t1);
                 Long aLong = jsonObject.getJSONObject("song").getLong("mid");
                 if(aLong.equals(mid)){
                     return true;
                 }
             }
             return false;
         }
        int getsongpos(String room_id,Long mid){
        BoundListOperations boundListOperations = redisTemplate.boundListOps(room_id);
        List range = boundListOperations.range(0, -1);
        for(int i=1;i<range.size();i++){
            String t1= (String)range.get(i);
            JSONObject jsonObject = JSONObject.parseObject(t1);
            Long aLong = jsonObject.getJSONObject("song").getLong("mid");
            if(aLong.equals(mid)){
                return i;
            }
        }
        return -1;
    }

}
